﻿#include "CStatisticsChat.h"
#include "CGlobal.h"

CStatisticsChat::CStatisticsChat(CDevDataCam* pDevData, QWidget *parent)
	: m_pDevData(pDevData),QWidget(parent)
{
	ui.setupUi(this);
	m_nType = 0;
	// 初始化折线图
	initLineChart();
	// 初始化柱状图
	initBarChart();
	m_pTimer = new QTimer(this);
	connect(m_pTimer, SIGNAL(timeout()), this, SLOT(slotRefreshUI()));
	// 连接Tab切换信号
	connect(ui.tabWidget, &QTabWidget::currentChanged, [this](int index) {
		m_nType = index;
	});
	slotRefreshUI();
}

CStatisticsChat::~CStatisticsChat()
{
	if (m_pTimer)
	{
		m_pTimer->stop();
		// 断开所有连接，防止信号队列中的调用
		disconnect(m_pTimer, nullptr, this, nullptr);
		delete m_pTimer;
		m_pTimer = nullptr;
	}
	// 清理折线图标签
	for (auto label : m_lineLabels) delete label;
	m_lineLabels.clear();

	// 清理柱状图标签
	for (auto label : m_barLabels) delete label;
	m_barLabels.clear();
}

void CStatisticsChat::initLineChart()
{
	m_lineLabels.clear();  // 确保容器为空
	ui.widget->setMinimumHeight(600);
	// 初始化图表
	m_pLineSeriesChart = new QChart();
	m_pLineSeriesChart->setTitle(A2T("摄像头报警统计图"));
	ui.widget->setChart(m_pLineSeriesChart);
	ui.widget->setRenderHint(QPainter::Antialiasing);
	// 调整图表内边距（标题上移关键）
	m_pLineSeriesChart->setMargins(QMargins(0, 10, 0, 20)); // 上边距10，下边距20
	// 创建折线序列
	m_pSeries = new QLineSeries();
	m_pSeries->setName(A2T("报警统计折线图"));
	m_pSeries->setPointsVisible(true); // 显示数据点
	m_pSeries->setPointLabelsVisible(false);
	m_pSeries->setBrush(QBrush(QColor(255, 0, 0, 150))); // 半透明红色填充
	m_pSeries->setPen(QPen(Qt::blue, 2)); // 蓝色边框2px宽

	// 标签背景增强
	m_pSeries->setPointLabelsClipping(false); // 允许标签超出图表区
	m_pSeries->setColor(Qt::blue); // 设置明显颜色
	m_pLineSeriesChart->addSeries(m_pSeries);

	QBarCategoryAxis *axisX = new QBarCategoryAxis();
	//axisX->setTitleText(A2T("报警类型")); // 设置X轴标题
	QStringList categories;
	categories << A2T("堆煤煤流占比") << A2T("皮带异物") << A2T("大块煤检测") << A2T("皮带跑偏算法") << A2T("安全帽反光衣") << A2T("烟雾火点")
		<< A2T("抽烟打电话") << A2T("测温报警") << A2T("周界防范")<<A2T("传送带堵料") << A2T("抛洒滴漏") <<A2T("街面行为");
	axisX->append(categories);

	m_pLineSeriesChart->addAxis(axisX, Qt::AlignBottom);
	// 设置标签倾斜角度
	//axisX->setLabelsAngle(60);  // 顺时针旋转60度
	m_pSeries->attachAxis(axisX); // 关联折线序列

	m_pLineSeriesAxisY = new QValueAxis;
	m_pLineSeriesAxisY->setTitleText(A2T("记录数"));
	m_pLineSeriesAxisY->applyNiceNumbers(); // 启用自动优化刻度
	m_pLineSeriesChart->addAxis(m_pLineSeriesAxisY, Qt::AlignLeft);
	m_pSeries->attachAxis(m_pLineSeriesAxisY);

	// 创建微软雅黑字体
	QFont msyhFont("Microsoft YaHei", 8);  // 10pt大小
	// 设置X轴字体
	axisX->setLabelsFont(msyhFont);         // X轴标签字体
	axisX->setTitleFont(msyhFont);          // X轴标题字体
	// 设置Y轴字体
	m_pLineSeriesAxisY->setLabelsFont(msyhFont);    // Y轴标签字体
	m_pLineSeriesAxisY->setTitleFont(msyhFont);     // Y轴标题字体
}

void CStatisticsChat::initBarChart()
{
	m_barLabels.clear();
	ui.widget2->setMinimumHeight(600);

	// 创建图表
	m_pBarChart = new QChart();
	m_pBarChart->setTitle(A2T("摄像头报警统计图"));
	ui.widget2->setChart(m_pBarChart);
	m_pBarChart->setMargins(QMargins(0, 10, 0, 20));

	// 创建柱状图组件
	m_pBarSet = new QBarSet(A2T("报警统计柱状图"));
	*m_pBarSet << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0<< 0 << 0; // 初始化默认数据

	m_pBarSeries = new QBarSeries();
	m_pBarSeries->append(m_pBarSet);
	m_pBarChart->addSeries(m_pBarSeries); // 先添加系列

	// X轴设置
	QBarCategoryAxis *axisX = new QBarCategoryAxis();
	//axisX->setTitleText(A2T("报警类型"));
	QStringList categories;
	categories << A2T("堆煤煤流占比") << A2T("皮带异物") << A2T("大块煤检测") << A2T("皮带跑偏算法") << A2T("安全帽反光衣") << A2T("烟雾火点") 
		<< A2T("抽烟打电话")<<A2T("测温报警") << A2T("周界防范") << A2T("传送带堵料") << A2T("抛洒滴漏") <<A2T("街面行为");
	axisX->append(categories);
	//axisX->setLabelsAngle(60);

	// Y轴设置
	m_pBarAxisY = new QValueAxis();
	m_pBarAxisY->setTitleText(A2T("报警次数"));
	m_pBarAxisY->setRange(0, 10); // 初始范围

	// 添加坐标轴
	m_pBarChart->addAxis(axisX, Qt::AlignBottom);
	m_pBarChart->addAxis(m_pBarAxisY, Qt::AlignLeft);

	// 附加坐标轴到系列
	m_pBarSeries->attachAxis(axisX);
	m_pBarSeries->attachAxis(m_pBarAxisY);

	// 样式设置
	m_pBarSet->setColor(QColor(65, 105, 225)); // 皇家蓝
	m_pBarSet->setBorderColor(Qt::darkBlue);
	m_pBarSeries->setBarWidth(0.6);
	m_pBarSeries->setOpacity(0.9);

	// 创建微软雅黑字体
	QFont msyhFont("Microsoft YaHei", 8);  // 10pt大小
	// 设置X轴字体
	axisX->setLabelsFont(msyhFont);         // X轴标签字体
	axisX->setTitleFont(msyhFont);          // X轴标题字体
	// 设置Y轴字体
	m_pBarAxisY->setLabelsFont(msyhFont);    // Y轴标签字体
	m_pBarAxisY->setTitleFont(msyhFont);     // Y轴标题字体
}

void CStatisticsChat::refresLine()
{
	// 加锁获取数据
	m_pDevData->m_pMutex->lock();
	QVector<AlarmItem> vecAlarm = m_pDevData->m_vecAlarm;
	m_pDevData->m_pMutex->unlock();

	if (vecAlarm.size() == 0)
	{
		return;
	}

	// 初始化计数器
	QVector<int> counts(12, 0);
	int maxCount = 0;

	// 统计报警数据
	for (const AlarmItem& item : vecAlarm)
	{
		if (item.sAlarmType == A2T("堆煤煤流占比")) counts[0]++;
		else if (item.sAlarmType == A2T("皮带异物")) counts[1]++;
		else if (item.sAlarmType == A2T("大块煤检测")) counts[2]++;
		else if (item.sAlarmType == A2T("皮带跑偏算法")) counts[3]++;
		else if (item.sAlarmType == A2T("安全帽反光衣")) counts[4]++;
		else if (item.sAlarmType == A2T("烟雾火点")) counts[5]++;
		else if (item.sAlarmType == A2T("抽烟打电话")) counts[6]++;
		else if (item.sAlarmType == A2T("测温报警")) counts[7]++;
		else if (item.sAlarmType == A2T("周界防范")) counts[8]++;
		else if (item.sAlarmType == A2T("传送带堵料")) counts[9]++;
		else if (item.sAlarmType == A2T("抛洒滴漏")) counts[10]++;
		else if (item.sAlarmType == A2T("街面行为")) counts[11]++;
	}

	// 找出最大值
	for (int count : counts)
	{
		if (count > maxCount) maxCount = count;
	}

	// 准备数据点
	QVector<QPointF> data;
	for (int i = 0; i < 12; i++)
	{
		data << QPointF(i, counts[i]);
	}

	// 更新折线图数据
	m_pSeries->replace(data);

	// 调整Y轴范围，留出一些空间给标签
	m_pLineSeriesAxisY->setRange(0, maxCount > 0 ? maxCount * 1.3 : 5);

	// 清除旧标签
	for (auto label : m_lineLabels)
	{
		m_pLineSeriesChart->scene()->removeItem(label);
		delete label;
	}
	m_lineLabels.clear();

	// 报警类型名称
	QStringList alarmNames =
	{
		A2T("堆煤煤流占比"),
		A2T("皮带异物"),
		A2T("大块煤检测"),
		A2T("皮带跑偏算法"),
		A2T("安全帽反光衣"),
		A2T("烟雾火点"),
		A2T("抽烟打电话"),
		A2T("测温报警"),
		A2T("周界防范"),
		A2T("传送带堵料"),
		A2T("抛洒滴漏"),
		A2T("街面行为")
	};

	// 创建新标签
	for (int i = 0; i < data.size(); ++i) {
		const QPointF& point = data[i];
		QString labelText = QString("(%1,%2)")
			.arg(alarmNames[i])
			.arg(point.y());

		// 创建标签对象
		QGraphicsSimpleTextItem* label = new QGraphicsSimpleTextItem(labelText);
		label->setFont(QFont("Microsoft YaHei", 8));

		// 计算标签位置
		QPointF labelPos = m_pLineSeriesChart->mapToPosition(point, m_pSeries);

		// 调整标签位置 - 在数据点上方
		qreal xOffset = -label->boundingRect().width() / 2;
		qreal yOffset = -label->boundingRect().height() - 10; // 数据点上方10像素

		// 对于值为0的数据点，将标签放在X轴下方
		if (point.y() == 0) {
			yOffset = 15; // X轴下方15像素
		}

		labelPos += QPointF(xOffset, yOffset);

		// 确保标签不会超出图表区域
		QRectF plotArea = m_pLineSeriesChart->plotArea();
		if (labelPos.x() < plotArea.left()) {
			labelPos.setX(plotArea.left() + 5);
		}
		if (labelPos.x() + label->boundingRect().width() > plotArea.right()) {
			labelPos.setX(plotArea.right() - label->boundingRect().width() - 5);
		}
		if (labelPos.y() < plotArea.top()) {
			labelPos.setY(plotArea.top() + 5);
		}
		if (labelPos.y() + label->boundingRect().height() > plotArea.bottom()) {
			labelPos.setY(plotArea.bottom() - label->boundingRect().height() - 5);
		}

		label->setPos(labelPos);

		// 添加到图表
		m_pLineSeriesChart->scene()->addItem(label);
		m_lineLabels.append(label);
	}

	// 刷新图表
	m_pLineSeriesChart->update();
}

void CStatisticsChat::refresBar()
{
	// 线程安全锁
	m_pDevData->m_pMutex->lock();
	QVector<AlarmItem> vecAlarm = m_pDevData->m_vecAlarm;
	m_pDevData->m_pMutex->unlock();
	// 添加安全检查：确保图表和场景有效
	if (!m_pBarChart || !m_pBarChart->scene()) 
	{
		return;
	}
	if (vecAlarm.size() == 0)
	{
		return;
	}
	// 初始化计数器
	QVector<int> counts(12, 0);
	int maxCount = 0;

	// 统计报警数据
	for (const AlarmItem& item : vecAlarm)
	{
		if (item.sAlarmType == A2T("堆煤煤流占比")) counts[0]++;
		else if (item.sAlarmType == A2T("皮带异物")) counts[1]++;
		else if (item.sAlarmType == A2T("大块煤检测")) counts[2]++;
		else if (item.sAlarmType == A2T("皮带跑偏算法")) counts[3]++;
		else if (item.sAlarmType == A2T("安全帽反光衣")) counts[4]++;
		else if (item.sAlarmType == A2T("烟雾火点")) counts[5]++;
		else if (item.sAlarmType == A2T("抽烟打电话")) counts[6]++;
		else if (item.sAlarmType == A2T("测温报警")) counts[7]++;
		else if (item.sAlarmType == A2T("周界防范")) counts[8]++;
		else if (item.sAlarmType == A2T("传送带堵料")) counts[9]++;
		else if (item.sAlarmType == A2T("抛洒滴漏")) counts[10]++;
		else if (item.sAlarmType == A2T("街面行为")) counts[11]++;

		// 更新最大值
		for (int count : counts)
		{
			if (count > maxCount) maxCount = count;
		}
	}
	// 调整Y轴范围 - 修复关键问题
	if (maxCount == 0)
	{
		// 当所有值都为0时，设置一个默认的最小范围
		m_pBarAxisY->setRange(0, 10); // 设置一个默认范围
	}
	else
	{
		m_pBarAxisY->setRange(0, maxCount * 1.2);
	}
	// 准备数据点
	QVector<QPointF> data;
	for (int i = 0; i < 12; i++) {
		data << QPointF(i, counts[i]);
	}

	// 更新柱状图数据
	m_pBarSet->remove(0, m_pBarSet->count()); // 清除旧数据
	for (const QPointF& point : data) {
		*m_pBarSet << point.y(); // 添加新数据
	}

	// 调整Y轴范围
	m_pBarAxisY->setRange(0, maxCount * 1.2);

	// 清除旧标签
	for (auto label : m_barLabels) {
		if (m_pBarChart && m_pBarChart->scene()) {
			m_pBarChart->scene()->removeItem(label);
		}
		delete label;
	}
	m_barLabels.clear();

	// 报警类型名称
	QStringList alarmNames = {
		A2T("堆煤煤流占比"),
		A2T("皮带异物"),
		A2T("大块煤检测"),
		A2T("皮带跑偏算法"),
		A2T("安全帽反光衣"),
		A2T("烟雾火点"),
		A2T("抽烟打电话"),
		A2T("测温报警"),
		A2T("周界防范"),
		A2T("传送带堵料"),
		A2T("抛洒滴漏"),
		A2T("街面行为")
	};

	// 创建新标签
	if (m_pBarChart && m_pBarChart->scene()) {
		for (int i = 0; i < data.size(); ++i) {
			const QPointF& point = data[i];
			QString labelText = QString("(%1, %2)")
				.arg(alarmNames[i])
				.arg(point.y());

			// 创建标签对象
			QGraphicsSimpleTextItem* label = new QGraphicsSimpleTextItem(labelText);
			label->setFont(QFont("Microsoft YaHei", 8));
			label->setBrush(QBrush(Qt::black));

			// 计算标签位置 - 修复位置计算
			QPointF labelPos;
			QRectF plotArea = m_pBarChart->plotArea();

			if (point.y() == 0)
			{
				// 对于值为0的柱子，将标签放在X轴下方
				labelPos = m_pBarChart->mapToPosition(QPointF(i, 0), m_pBarSeries);
				labelPos.setX(labelPos.x() - label->boundingRect().width() / 2);

				// 确保有有效的Y坐标位置
				if (plotArea.isValid())
				{
					labelPos.setY(plotArea.bottom() - 20); // X轴下方5像素
				}
				else
				{
					labelPos.setY(100); // 备用位置
				}
			}
			else
			{
				// 正常柱子，放在柱子顶部
				labelPos = m_pBarChart->mapToPosition(QPointF(i, point.y()), m_pBarSeries);
				labelPos.setX(labelPos.x() - label->boundingRect().width() / 2);
				labelPos.setY(labelPos.y() - 20);
			}

			// 确保标签不会超出图表区域
			if (plotArea.isValid())
			{
				if (labelPos.x() < plotArea.left())
				{
					labelPos.setX(plotArea.left());
				}
				if (labelPos.x() + label->boundingRect().width() > plotArea.right())
				{
					labelPos.setX(plotArea.right() - label->boundingRect().width());
				}
				if (labelPos.y() < plotArea.top())
				{
					labelPos.setY(plotArea.top());
				}
			}

			label->setPos(labelPos);

			// 添加到图表
			m_pBarChart->scene()->addItem(label);
			m_barLabels.append(label);
		}
	}

	// 刷新柱状图
	if (m_pBarChart) 
	{
		m_pBarChart->update();
	}
}

void CStatisticsChat::refreshData(bool bRefresh)
{
	if (bRefresh)
	{
		m_pTimer->start(1000);
	}
	else
	{
		m_pTimer->stop();
	}
}

void CStatisticsChat::slotRefreshUI()
{
	if (!isVisible())
	{
		return;
	}
	if (m_nType == 0)
	{
		refresLine();
	}
	else
	{
		refresBar();
	}
	
}
